/**
 * 有序列表,无序列表插件
 * @file
 * @since 1.2.6.1
 */

UE.plugins["list"] = function () {
    var me = this,
        notExchange = {
            TD: 1,
            PRE: 1,
            BLOCKQUOTE: 1
        };
    // var customStyle = {
    //     cn: "cn-1-",
    //     cn1: "cn-2-",
    //     cn2: "cn-3-",
    //     num: "num-1-",
    //     num1: "num-2-",
    //     num2: "num-3-",
    //     dash: "dash",
    //     dot: "dot"
    // };

    me.setOpt({
        autoTransWordToList: false,
        insertorderedlist: {
            // num: "",
            // num1: "",
            // num2: "",
            // cn: "",
            // cn1: "",
            // cn2: "",
            decimal: "",
            "lower-alpha": "",
            "lower-roman": "",
            "upper-alpha": "",
            "upper-roman": ""
        },
        insertunorderedlist: {
            circle: "",
            disc: "",
            square: "",
            // dash: "",
            // dot: ""
        },
        listDefaultPaddingLeft: "30",
        listiconpath: "http://bs.baidu.com/listicon/",
        maxListLevel: -1, //-1不限制
        disablePInList: false
    });

    function listToArray(list) {
        var arr = [];
        for (var p in list) {
            arr.push(p);
        }
        return arr;
    }

    var listStyle = {
        OL: listToArray(me.options.insertorderedlist),
        UL: listToArray(me.options.insertunorderedlist)
    };
    var liiconpath = me.options.listiconpath;

    //根据用户配置，调整customStyle
    // for (var s in customStyle) {
    //     if (
    //         !me.options.insertorderedlist.hasOwnProperty(s) &&
    //         !me.options.insertunorderedlist.hasOwnProperty(s)
    //     ) {
    //         delete customStyle[s];
    //     }
    // }

    me.ready(function () {
        var customCss = [];
        // for (var p in customStyle) {
        //     if (p == "dash" || p == "dot") {
        //         customCss.push(
        //             "li.list-" +
        //             customStyle[p] +
        //             "{background-image:url(" +
        //             liiconpath +
        //             customStyle[p] +
        //             ".gif)}"
        //         );
        //         customCss.push(
        //             "ul.custom_" +
        //             p +
        //             "{list-style:none;}ul.custom_" +
        //             p +
        //             " li{background-position:0 3px;background-repeat:no-repeat}"
        //         );
        //     } else {
        //         for (var i = 0; i < 99; i++) {
        //             customCss.push(
        //                 "li.list-" +
        //                 customStyle[p] +
        //                 i +
        //                 "{background-image:url(" +
        //                 liiconpath +
        //                 "list-" +
        //                 customStyle[p] +
        //                 i +
        //                 ".gif)}"
        //             );
        //         }
        //         customCss.push(
        //             "ol.custom_" +
        //             p +
        //             "{list-style:none;}ol.custom_" +
        //             p +
        //             " li{background-position:0 3px;background-repeat:no-repeat}"
        //         );
        //     }
        //     switch (p) {
        //         case "cn":
        //             customCss.push("li.list-" + p + "-paddingleft-1{padding-left:25px}");
        //             customCss.push("li.list-" + p + "-paddingleft-2{padding-left:40px}");
        //             customCss.push("li.list-" + p + "-paddingleft-3{padding-left:55px}");
        //             break;
        //         case "cn1":
        //             customCss.push("li.list-" + p + "-paddingleft-1{padding-left:30px}");
        //             customCss.push("li.list-" + p + "-paddingleft-2{padding-left:40px}");
        //             customCss.push("li.list-" + p + "-paddingleft-3{padding-left:55px}");
        //             break;
        //         case "cn2":
        //             customCss.push("li.list-" + p + "-paddingleft-1{padding-left:40px}");
        //             customCss.push("li.list-" + p + "-paddingleft-2{padding-left:55px}");
        //             customCss.push("li.list-" + p + "-paddingleft-3{padding-left:68px}");
        //             break;
        //         case "num":
        //         case "num1":
        //             customCss.push("li.list-" + p + "-paddingleft-1{padding-left:25px}");
        //             break;
        //         case "num2":
        //             customCss.push("li.list-" + p + "-paddingleft-1{padding-left:35px}");
        //             customCss.push("li.list-" + p + "-paddingleft-2{padding-left:40px}");
        //             break;
        //         case "dash":
        //             customCss.push("li.list-" + p + "-paddingleft{padding-left:35px}");
        //             break;
        //         case "dot":
        //             customCss.push("li.list-" + p + "-paddingleft{padding-left:20px}");
        //     }
        // }
        customCss.push(".list-paddingleft-1{padding-left:0}");
        customCss.push(
            ".list-paddingleft-2{padding-left:" +
            me.options.listDefaultPaddingLeft +
            "px}"
        );
        customCss.push(
            ".list-paddingleft-3{padding-left:" +
            me.options.listDefaultPaddingLeft * 2 +
            "px}"
        );
        //如果不给宽度会在自定应样式里出现滚动条
        utils.cssRule(
            "list",
            "ol,ul{margin:0;pading:0;" +
            (browser.ie ? "" : "width:95%") +
            "}li{clear:both;}" +
            customCss.join("\n"),
            me.document
        );
    });
    //单独处理剪切的问题
    me.ready(function () {
        domUtils.on(me.body, "cut", function () {
            setTimeout(function () {
                var rng = me.selection.getRange(),
                    li;
                //trace:3416
                if (!rng.collapsed) {
                    if (
                        (li = domUtils.findParentByTagName(rng.startContainer, "li", true))
                    ) {
                        if (!li.nextSibling && domUtils.isEmptyBlock(li)) {
                            var pn = li.parentNode,
                                node;
                            if ((node = pn.previousSibling)) {
                                domUtils.remove(pn);
                                rng.setStartAtLast(node).collapse(true);
                                rng.select(true);
                            } else if ((node = pn.nextSibling)) {
                                domUtils.remove(pn);
                                rng.setStartAtFirst(node).collapse(true);
                                rng.select(true);
                            } else {
                                var tmpNode = me.document.createElement("p");
                                domUtils.fillNode(me.document, tmpNode);
                                pn.parentNode.insertBefore(tmpNode, pn);
                                domUtils.remove(pn);
                                rng.setStart(tmpNode, 0).collapse(true);
                                rng.select(true);
                            }
                        }
                    }
                }
            });
        });
    });

    function getStyle(node) {
        var cls = node.className;
        if (domUtils.hasClass(node, /custom_/)) {
            return cls.match(/custom_(\w+)/)[1];
        }
        return domUtils.getStyle(node, "list-style-type");
    }

    me.addListener("beforepaste", function (type, html) {
        var me = this,
            rng = me.selection.getRange(),
            li;
        var root = UE.htmlparser(html.html, true);
        if ((li = domUtils.findParentByTagName(rng.startContainer, "li", true))) {
            var list = li.parentNode,
                tagName = list.tagName === "OL" ? "ul" : "ol";
            utils.each(root.getNodesByTagName(tagName), function (n) {
                n.tagName = list.tagName;
                n.setAttr();
                if (n.parentNode === root) {
                    type = getStyle(list) || (list.tagName == "OL" ? "decimal" : "disc");
                } else {
                    var className = n.parentNode.getAttr("class");
                    if (className && /custom_/.test(className)) {
                        type = className.match(/custom_(\w+)/)[1];
                    } else {
                        type = n.parentNode.getStyle("list-style-type");
                    }
                    if (!type) {
                        type = list.tagName === "OL" ? "decimal" : "disc";
                    }
                }
                var index = utils.indexOf(listStyle[list.tagName], type);
                if (n.parentNode !== root)
                    index = index + 1 === listStyle[list.tagName].length ? 0 : index + 1;
                var currentStyle = listStyle[list.tagName][index];
                // if (customStyle[currentStyle]) {
                //     n.setAttr("class", "custom_" + currentStyle);
                // } else {
                n.setStyle("list-style-type", currentStyle);
                // }
            });
        }

        html.html = root.toHtml();
    });
    //导出时，去掉p标签
    me.getOpt("disablePInList") === true &&
    me.addOutputRule(function (root) {
        utils.each(root.getNodesByTagName("li"), function (li) {
            var newChildrens = [],
                index = 0;
            utils.each(li.children, function (n) {
                if (n.tagName == "p") {
                    var tmpNode;
                    while ((tmpNode = n.children.pop())) {
                        newChildrens.splice(index, 0, tmpNode);
                        tmpNode.parentNode = li;
                        lastNode = tmpNode;
                    }
                    tmpNode = newChildrens[newChildrens.length - 1];
                    if (
                        !tmpNode ||
                        tmpNode.type !== "element" ||
                        tmpNode.tagName !== "br"
                    ) {
                        var br = UE.uNode.createElement("br");
                        br.parentNode = li;
                        newChildrens.push(br);
                    }

                    index = newChildrens.length;
                }
            });
            if (newChildrens.length) {
                li.children = newChildrens;
            }
        });
    });
    //进入编辑器的li要套p标签
    me.addInputRule(function (root) {
        utils.each(root.getNodesByTagName("li"), function (li) {
            var tmpP = UE.uNode.createElement("p");
            for (var i = 0, ci; (ci = li.children[i]);) {
                if (ci.type === "text" || dtd.p[ci.tagName]) {
                    tmpP.appendChild(ci);
                } else {
                    if (tmpP.firstChild()) {
                        li.insertBefore(tmpP, ci);
                        tmpP = UE.uNode.createElement("p");
                        i = i + 2;
                    } else {
                        i++;
                    }
                }
            }
            if ((tmpP.firstChild() && !tmpP.parentNode) || !li.firstChild()) {
                li.appendChild(tmpP);
            }
            //trace:3357
            //p不能为空
            if (!tmpP.firstChild()) {
                tmpP.innerHTML(browser.ie ? "&nbsp;" : "<br/>");
            }
            //去掉末尾的空白
            var p = li.firstChild();
            var lastChild = p.lastChild();
            if (
                lastChild &&
                lastChild.type === "text" &&
                /^\s*$/.test(lastChild.data)
            ) {
                p.removeChild(lastChild);
            }
        });
        if (me.options.autoTransWordToList) {
            var orderlisttype = {
                    num1: /^\d+\)/,
                    decimal: /^\d+\./,
                    "lower-alpha": /^[a-z]+\)/,
                    "upper-alpha": /^[A-Z]+\./,
                    cn: /^[\u4E00\u4E8C\u4E09\u56DB\u516d\u4e94\u4e03\u516b\u4e5d]+[\u3001]/,
                    cn2: /^\([\u4E00\u4E8C\u4E09\u56DB\u516d\u4e94\u4e03\u516b\u4e5d]+\)/
                },
                unorderlisttype = {
                    square: "n"
                };

            function checkListType(content, container) {
                var span = container.firstChild();
                if (
                    span &&
                    span.type === "element" &&
                    span.tagName === "span" &&
                    /Wingdings|Symbol/.test(span.getStyle("font-family"))
                ) {
                    for (var p in unorderlisttype) {
                        if (unorderlisttype[p] == span.data) {
                            return p;
                        }
                    }
                    return "disc";
                }
                for (var p in orderlisttype) {
                    if (orderlisttype[p].test(content)) {
                        return p;
                    }
                }
            }

            utils.each(root.getNodesByTagName("p"), function (node) {
                if (node.getAttr("class") !== "MsoListParagraph") {
                    return;
                }

                //word粘贴过来的会带有margin要去掉,但这样也可能会误命中一些央视
                node.setStyle("margin", "");
                node.setStyle("margin-left", "");
                node.setAttr("class", "");

                function appendLi(list, p, type) {
                    if (list.tagName === "ol") {
                        if (browser.ie) {
                            var first = p.firstChild();
                            if (
                                first.type === "element" &&
                                first.tagName === "span" &&
                                orderlisttype[type].test(first.innerText())
                            ) {
                                p.removeChild(first);
                            }
                        } else {
                            p.innerHTML(p.innerHTML().replace(orderlisttype[type], ""));
                        }
                    } else {
                        p.removeChild(p.firstChild());
                    }

                    var li = UE.uNode.createElement("li");
                    li.appendChild(p);
                    list.appendChild(li);
                }

                var tmp = node,
                    type,
                    cacheNode = node;

                if (
                    node.parentNode.tagName !== "li" &&
                    (type = checkListType(node.innerText(), node))
                ) {
                    var list = UE.uNode.createElement(
                        me.options.insertorderedlist.hasOwnProperty(type) ? "ol" : "ul"
                    );
                    // if (customStyle[type]) {
                    //     list.setAttr("class", "custom_" + type);
                    // } else {
                    list.setStyle("list-style-type", type);
                    // }
                    while (
                        node &&
                        node.parentNode.tagName !== "li" &&
                        checkListType(node.innerText(), node)
                        ) {
                        tmp = node.nextSibling();
                        if (!tmp) {
                            node.parentNode.insertBefore(list, node);
                        }
                        appendLi(list, node, type);
                        node = tmp;
                    }
                    if (!list.parentNode && node && node.parentNode) {
                        node.parentNode.insertBefore(list, node);
                    }
                }
                var span = cacheNode.firstChild();
                if (
                    span &&
                    span.type == "element" &&
                    span.tagName == "span" &&
                    /^\s*(&nbsp;)+\s*$/.test(span.innerText())
                ) {
                    span.parentNode.removeChild(span);
                }
            });
        }
    });

    //调整索引标签
    me.addListener("contentchange", function () {
        adjustListStyle(me.document);
    });

    function adjustListStyle(doc, ignore) {
        utils.each(domUtils.getElementsByTagName(doc, "ol ul"), function (node) {
            if (!domUtils.inDoc(node, doc)) return;

            var parent = node.parentNode;
            if (parent.tagName === node.tagName) {
                var nodeStyleType =
                    getStyle(node) || (node.tagName === "OL" ? "decimal" : "disc"),
                    parentStyleType =
                        getStyle(parent) || (parent.tagName === "OL" ? "decimal" : "disc");
                if (nodeStyleType === parentStyleType) {
                    var styleIndex = utils.indexOf(
                        listStyle[node.tagName],
                        nodeStyleType
                    );
                    styleIndex = styleIndex + 1 === listStyle[node.tagName].length
                        ? 0
                        : styleIndex + 1;
                    setListStyle(node, listStyle[node.tagName][styleIndex]);
                }
            }
            var index = 0,
                type = 2;
            if (domUtils.hasClass(node, /custom_/)) {
                if (
                    !(
                        /[ou]l/i.test(parent.tagName) &&
                        domUtils.hasClass(parent, /custom_/)
                    )
                ) {
                    type = 1;
                }
            } else {
                if (
                    /[ou]l/i.test(parent.tagName) &&
                    domUtils.hasClass(parent, /custom_/)
                ) {
                    type = 3;
                }
            }

            var style = domUtils.getStyle(node, "list-style-type");
            style && (node.style.cssText = "list-style-type:" + style);
            node.className =
                utils.trim(node.className.replace(/list-paddingleft-\w+/, "")) +
                " list-paddingleft-" +
                type;
            utils.each(domUtils.getElementsByTagName(node, "li"), function (li) {
                li.style.cssText && (li.style.cssText = "");
                if (!li.firstChild) {
                    domUtils.remove(li);
                    return;
                }
                if (li.parentNode !== node) {
                    return;
                }
                index++;
                if (domUtils.hasClass(node, /custom_/)) {
                    var paddingLeft = 1,
                        currentStyle = getStyle(node);
                    if (node.tagName === "OL") {
                        if (currentStyle) {
                            switch (currentStyle) {
                                case "cn":
                                case "cn1":
                                case "cn2":
                                    if (
                                        index > 10 &&
                                        (index % 10 === 0 || (index > 10 && index < 20))
                                    ) {
                                        paddingLeft = 2;
                                    } else if (index > 20) {
                                        paddingLeft = 3;
                                    }
                                    break;
                                case "num2":
                                    if (index > 9) {
                                        paddingLeft = 2;
                                    }
                            }
                        }
                        li.className =
                            // "list-" +
                            // customStyle[currentStyle] +
                            // index +
                            // " " +
                            "list-" +
                            currentStyle +
                            "-paddingleft-" +
                            paddingLeft;
                    } else {
                        li.className =
                            // "list-" +
                            // customStyle[currentStyle] +
                            // " " +
                            "list-" +
                            currentStyle +
                            "-paddingleft";
                    }
                } else {
                    li.className = li.className.replace(/list-[\w\-]+/gi, "");
                }
                var className = li.getAttribute("class");
                if (className !== null && !className.replace(/\s/g, "")) {
                    domUtils.removeAttributes(li, "class");
                }
            });
            !ignore &&
            adjustList(
                node,
                node.tagName.toLowerCase(),
                getStyle(node) || domUtils.getStyle(node, "list-style-type"),
                true
            );
        });
    }

    function adjustList(list, tag, style, ignoreEmpty) {
        var nextList = list.nextSibling;
        if (
            nextList &&
            nextList.nodeType === 1 &&
            nextList.tagName.toLowerCase() === tag &&
            (getStyle(nextList) ||
                domUtils.getStyle(nextList, "list-style-type") ||
                (tag == "ol" ? "decimal" : "disc")) == style
        ) {
            domUtils.moveChild(nextList, list);
            if (nextList.childNodes.length === 0) {
                domUtils.remove(nextList);
            }
        }
        if (nextList && domUtils.isFillChar(nextList)) {
            domUtils.remove(nextList);
        }
        var preList = list.previousSibling;
        if (
            preList &&
            preList.nodeType === 1 &&
            preList.tagName.toLowerCase() == tag &&
            (getStyle(preList) ||
                domUtils.getStyle(preList, "list-style-type") ||
                (tag == "ol" ? "decimal" : "disc")) === style
        ) {
            domUtils.moveChild(list, preList);
        }
        if (preList && domUtils.isFillChar(preList)) {
            domUtils.remove(preList);
        }
        !ignoreEmpty && domUtils.isEmptyBlock(list) && domUtils.remove(list);
        if (getStyle(list)) {
            adjustListStyle(list.ownerDocument, true);
        }
    }

    function setListStyle(list, style) {
        // if (customStyle[style]) {
        //     list.className = "custom_" + style;
        // }
        try {
            domUtils.setStyle(list, "list-style-type", style);
        } catch (e) {
        }
    }

    function clearEmptySibling(node) {
        var tmpNode = node.previousSibling;
        if (tmpNode && domUtils.isEmptyBlock(tmpNode)) {
            domUtils.remove(tmpNode);
        }
        tmpNode = node.nextSibling;
        if (tmpNode && domUtils.isEmptyBlock(tmpNode)) {
            domUtils.remove(tmpNode);
        }
    }

    me.addListener("keydown", function (type, evt) {
        function preventAndSave() {
            evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
            me.fireEvent("contentchange");
            me.undoManger && me.undoManger.save();
        }

        function findList(node, filterFn) {
            while (node && !domUtils.isBody(node)) {
                if (filterFn(node)) {
                    return null;
                }
                if (node.nodeType === 1 && /[ou]l/i.test(node.tagName)) {
                    return node;
                }
                node = node.parentNode;
            }
            return null;
        }

        var keyCode = evt.keyCode || evt.which;
        if (keyCode === 13 && !evt.shiftKey) {
            //回车
            var rng = me.selection.getRange(),
                parent = domUtils.findParent(
                    rng.startContainer,
                    function (node) {
                        return domUtils.isBlockElm(node);
                    },
                    true
                ),
                li = domUtils.findParentByTagName(rng.startContainer, "li", true);
            if (parent && parent.tagName !== "PRE" && !li) {
                var html = parent.innerHTML.replace(
                    new RegExp(domUtils.fillChar, "g"),
                    ""
                );
                if (/^\s*1\s*\.[^\d]/.test(html)) {
                    parent.innerHTML = html.replace(/^\s*1\s*\./, "");
                    rng.setStartAtLast(parent).collapse(true).select();
                    me.__hasEnterExecCommand = true;
                    me.execCommand("insertorderedlist");
                    me.__hasEnterExecCommand = false;
                }
            }
            var range = me.selection.getRange(),
                start = findList(range.startContainer, function (node) {
                    return node.tagName === "TABLE";
                }),
                end = range.collapsed
                    ? start
                    : findList(range.endContainer, function (node) {
                        return node.tagName === "TABLE";
                    });

            if (start && end && start === end) {
                if (!range.collapsed) {
                    start = domUtils.findParentByTagName(
                        range.startContainer,
                        "li",
                        true
                    );
                    end = domUtils.findParentByTagName(range.endContainer, "li", true);
                    if (start && end && start === end) {
                        range.deleteContents();
                        li = domUtils.findParentByTagName(range.startContainer, "li", true);
                        if (li && domUtils.isEmptyBlock(li)) {
                            pre = li.previousSibling;
                            next = li.nextSibling;
                            p = me.document.createElement("p");

                            domUtils.fillNode(me.document, p);
                            parentList = li.parentNode;
                            if (pre && next) {
                                range.setStart(next, 0).collapse(true).select(true);
                                domUtils.remove(li);
                            } else {
                                if ((!pre && !next) || !pre) {
                                    parentList.parentNode.insertBefore(p, parentList);
                                } else {
                                    li.parentNode.parentNode.insertBefore(
                                        p,
                                        parentList.nextSibling
                                    );
                                }
                                domUtils.remove(li);
                                if (!parentList.firstChild) {
                                    domUtils.remove(parentList);
                                }
                                range.setStart(p, 0).setCursor();
                            }
                            preventAndSave();
                            return;
                        }
                    } else {
                        var tmpRange = range.cloneRange(),
                            bk = tmpRange.collapse(false).createBookmark();

                        range.deleteContents();
                        tmpRange.moveToBookmark(bk);
                        var li = domUtils.findParentByTagName(
                            tmpRange.startContainer,
                            "li",
                            true
                        );

                        clearEmptySibling(li);
                        tmpRange.select();
                        preventAndSave();
                        return;
                    }
                }

                li = domUtils.findParentByTagName(range.startContainer, "li", true);

                if (li) {
                    if (domUtils.isEmptyBlock(li)) {
                        bk = range.createBookmark();
                        var parentList = li.parentNode;
                        if (li !== parentList.lastChild) {
                            domUtils.breakParent(li, parentList);
                            clearEmptySibling(li);
                        } else {
                            parentList.parentNode.insertBefore(li, parentList.nextSibling);
                            if (domUtils.isEmptyNode(parentList)) {
                                domUtils.remove(parentList);
                            }
                        }
                        //嵌套不处理
                        if (!dtd.$list[li.parentNode.tagName]) {
                            if (!domUtils.isBlockElm(li.firstChild)) {
                                p = me.document.createElement("p");
                                li.parentNode.insertBefore(p, li);
                                while (li.firstChild) {
                                    p.appendChild(li.firstChild);
                                }
                                domUtils.remove(li);
                            } else {
                                domUtils.remove(li, true);
                            }
                        }
                        range.moveToBookmark(bk).select();
                    } else {
                        var first = li.firstChild;
                        if (!first || !domUtils.isBlockElm(first)) {
                            var p = me.document.createElement("p");

                            !li.firstChild && domUtils.fillNode(me.document, p);
                            while (li.firstChild) {
                                p.appendChild(li.firstChild);
                            }
                            li.appendChild(p);
                            first = p;
                        }

                        var span = me.document.createElement("span");

                        range.insertNode(span);
                        domUtils.breakParent(span, li);

                        var nextLi = span.nextSibling;
                        first = nextLi.firstChild;

                        if (!first) {
                            p = me.document.createElement("p");

                            domUtils.fillNode(me.document, p);
                            nextLi.appendChild(p);
                            first = p;
                        }
                        if (domUtils.isEmptyNode(first)) {
                            first.innerHTML = "";
                            domUtils.fillNode(me.document, first);
                        }

                        range.setStart(first, 0).collapse(true).shrinkBoundary().select();
                        domUtils.remove(span);
                        var pre = nextLi.previousSibling;
                        if (pre && domUtils.isEmptyBlock(pre)) {
                            pre.innerHTML = "<p></p>";
                            domUtils.fillNode(me.document, pre.firstChild);
                        }
                    }
                    //                        }
                    preventAndSave();
                }
            }
        }
        if (keyCode === 8) {
            //修中ie中li下的问题
            range = me.selection.getRange();
            if (range.collapsed && domUtils.isStartInblock(range)) {
                tmpRange = range.cloneRange().trimBoundary();
                li = domUtils.findParentByTagName(range.startContainer, "li", true);
                //要在li的最左边，才能处理
                if (li && domUtils.isStartInblock(tmpRange)) {
                    start = domUtils.findParentByTagName(range.startContainer, "p", true);
                    if (start && start !== li.firstChild) {
                        var parentList = domUtils.findParentByTagName(start, ["ol", "ul"]);
                        domUtils.breakParent(start, parentList);
                        clearEmptySibling(start);
                        me.fireEvent("contentchange");
                        range.setStart(start, 0).setCursor(false, true);
                        me.fireEvent("saveScene");
                        domUtils.preventDefault(evt);
                        return;
                    }

                    if (li && (pre = li.previousSibling)) {
                        if (keyCode === 46 && li.childNodes.length) {
                            return;
                        }
                        //有可能上边的兄弟节点是个2级菜单，要追加到2级菜单的最后的li
                        if (dtd.$list[pre.tagName]) {
                            pre = pre.lastChild;
                        }
                        me.undoManger && me.undoManger.save();
                        first = li.firstChild;
                        if (domUtils.isBlockElm(first)) {
                            if (domUtils.isEmptyNode(first)) {
                                //                                    range.setEnd(pre, pre.childNodes.length).shrinkBoundary().collapse().select(true);
                                pre.appendChild(first);
                                range.setStart(first, 0).setCursor(false, true);
                                //first不是唯一的节点
                                while (li.firstChild) {
                                    pre.appendChild(li.firstChild);
                                }
                            } else {
                                span = me.document.createElement("span");
                                range.insertNode(span);
                                //判断pre是否是空的节点,如果是<p><br/></p>类型的空节点，干掉p标签防止它占位
                                if (domUtils.isEmptyBlock(pre)) {
                                    pre.innerHTML = "";
                                }
                                domUtils.moveChild(li, pre);
                                range.setStartBefore(span).collapse(true).select(true);

                                domUtils.remove(span);
                            }
                        } else {
                            if (domUtils.isEmptyNode(li)) {
                                var p = me.document.createElement("p");
                                pre.appendChild(p);
                                range.setStart(p, 0).setCursor();
                                //                                    range.setEnd(pre, pre.childNodes.length).shrinkBoundary().collapse().select(true);
                            } else {
                                range
                                    .setEnd(pre, pre.childNodes.length)
                                    .collapse()
                                    .select(true);
                                while (li.firstChild) {
                                    pre.appendChild(li.firstChild);
                                }
                            }
                        }
                        domUtils.remove(li);
                        me.fireEvent("contentchange");
                        me.fireEvent("saveScene");
                        domUtils.preventDefault(evt);
                        return;
                    }
                    //trace:980

                    if (li && !li.previousSibling) {
                        var parentList = li.parentNode;
                        var bk = range.createBookmark();
                        if (domUtils.isTagNode(parentList.parentNode, "ol ul")) {
                            parentList.parentNode.insertBefore(li, parentList);
                            if (domUtils.isEmptyNode(parentList)) {
                                domUtils.remove(parentList);
                            }
                        } else {
                            while (li.firstChild) {
                                parentList.parentNode.insertBefore(li.firstChild, parentList);
                            }

                            domUtils.remove(li);
                            if (domUtils.isEmptyNode(parentList)) {
                                domUtils.remove(parentList);
                            }
                        }
                        range.moveToBookmark(bk).setCursor(false, true);
                        me.fireEvent("contentchange");
                        me.fireEvent("saveScene");
                        domUtils.preventDefault(evt);
                        return;
                    }
                }
            }
        }
    });

    me.addListener("keyup", function (type, evt) {
        var keyCode = evt.keyCode || evt.which;
        if (keyCode == 8) {
            var rng = me.selection.getRange(),
                list;
            if (
                (list = domUtils.findParentByTagName(
                    rng.startContainer,
                    ["ol", "ul"],
                    true
                ))
            ) {
                adjustList(
                    list,
                    list.tagName.toLowerCase(),
                    getStyle(list) || domUtils.getComputedStyle(list, "list-style-type"),
                    true
                );
            }
        }
    });
    //处理tab键
    me.addListener("tabkeydown", function () {
        var range = me.selection.getRange();

        //控制级数
        function checkLevel(li) {
            if (me.options.maxListLevel != -1) {
                var level = li.parentNode,
                    levelNum = 0;
                while (/[ou]l/i.test(level.tagName)) {
                    levelNum++;
                    level = level.parentNode;
                }
                if (levelNum >= me.options.maxListLevel) {
                    return true;
                }
            }
        }

        //只以开始为准
        //todo 后续改进
        var li = domUtils.findParentByTagName(range.startContainer, "li", true);
        if (li) {
            var bk;
            if (range.collapsed) {
                if (checkLevel(li)) return true;
                var parentLi = li.parentNode,
                    list = me.document.createElement(parentLi.tagName),
                    index = utils.indexOf(
                        listStyle[list.tagName],
                        getStyle(parentLi) ||
                        domUtils.getComputedStyle(parentLi, "list-style-type")
                    );
                index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1;
                var currentStyle = listStyle[list.tagName][index];
                setListStyle(list, currentStyle);
                if (domUtils.isStartInblock(range)) {
                    me.fireEvent("saveScene");
                    bk = range.createBookmark();
                    parentLi.insertBefore(list, li);
                    list.appendChild(li);
                    adjustList(list, list.tagName.toLowerCase(), currentStyle);
                    me.fireEvent("contentchange");
                    range.moveToBookmark(bk).select(true);
                    return true;
                }
            } else {
                me.fireEvent("saveScene");
                bk = range.createBookmark();
                for (
                    var i = 0, closeList, parents = domUtils.findParents(li), ci;
                    (ci = parents[i++]);
                ) {
                    if (domUtils.isTagNode(ci, "ol ul")) {
                        closeList = ci;
                        break;
                    }
                }
                var current = li;
                if (bk.end) {
                    while (
                        current &&
                        !(
                            domUtils.getPosition(current, bk.end) &
                            domUtils.POSITION_FOLLOWING
                        )
                        ) {
                        if (checkLevel(current)) {
                            current = domUtils.getNextDomNode(current, false, null, function (
                                node
                            ) {
                                return node !== closeList;
                            });
                            continue;
                        }
                        var parentLi = current.parentNode,
                            list = me.document.createElement(parentLi.tagName),
                            index = utils.indexOf(
                                listStyle[list.tagName],
                                getStyle(parentLi) ||
                                domUtils.getComputedStyle(parentLi, "list-style-type")
                            );
                        var currentIndex = index + 1 == listStyle[list.tagName].length
                            ? 0
                            : index + 1;
                        var currentStyle = listStyle[list.tagName][currentIndex];
                        setListStyle(list, currentStyle);
                        parentLi.insertBefore(list, current);
                        while (
                            current &&
                            !(
                                domUtils.getPosition(current, bk.end) &
                                domUtils.POSITION_FOLLOWING
                            )
                            ) {
                            li = current.nextSibling;
                            list.appendChild(current);
                            if (!li || domUtils.isTagNode(li, "ol ul")) {
                                if (li) {
                                    while ((li = li.firstChild)) {
                                        if (li.tagName == "LI") {
                                            break;
                                        }
                                    }
                                } else {
                                    li = domUtils.getNextDomNode(current, false, null, function (
                                        node
                                    ) {
                                        return node !== closeList;
                                    });
                                }
                                break;
                            }
                            current = li;
                        }
                        adjustList(list, list.tagName.toLowerCase(), currentStyle);
                        current = li;
                    }
                }
                me.fireEvent("contentchange");
                range.moveToBookmark(bk).select();
                return true;
            }
        }
    });

    function getLi(start) {
        while (start && !domUtils.isBody(start)) {
            if (start.nodeName == "TABLE") {
                return null;
            }
            if (start.nodeName == "LI") {
                return start;
            }
            start = start.parentNode;
        }
    }

    /**
     * 有序列表，与“insertunorderedlist”命令互斥
     * @command insertorderedlist
     * @method execCommand
     * @param { String } command 命令字符串
     * @param { String } style 插入的有序列表类型，值为：decimal,lower-alpha,lower-roman,upper-alpha,upper-roman,cn,cn1,cn2,num,num1,num2
     * @example
     * ```javascript
     * editor.execCommand( 'insertorderedlist','decimal');
     * ```
     */
    /**
     * 查询当前选区内容是否有序列表
     * @command insertorderedlist
     * @method queryCommandState
     * @param { String } cmd 命令字符串
     * @return { int } 如果当前选区是有序列表返回1，否则返回0
     * @example
     * ```javascript
     * editor.queryCommandState( 'insertorderedlist' );
     * ```
     */
    /**
     * 查询当前选区内容是否有序列表
     * @command insertorderedlist
     * @method queryCommandValue
     * @param { String } cmd 命令字符串
     * @return { String } 返回当前有序列表的类型，值为null或decimal,lower-alpha,lower-roman,upper-alpha,upper-roman,cn,cn1,cn2,num,num1,num2
     * @example
     * ```javascript
     * editor.queryCommandValue( 'insertorderedlist' );
     * ```
     */

    /**
     * 无序列表，与“insertorderedlist”命令互斥
     * @command insertunorderedlist
     * @method execCommand
     * @param { String } command 命令字符串
     * @param { String } style 插入的无序列表类型，值为：circle,disc,square,dash,dot
     * @example
     * ```javascript
     * editor.execCommand( 'insertunorderedlist','circle');
     * ```
     */
    /**
     * 查询当前是否有word文档粘贴进来的图片
     * @command insertunorderedlist
     * @method insertunorderedlist
     * @param { String } command 命令字符串
     * @return { int } 如果当前选区是无序列表返回1，否则返回0
     * @example
     * ```javascript
     * editor.queryCommandState( 'insertunorderedlist' );
     * ```
     */
    /**
     * 查询当前选区内容是否有序列表
     * @command insertunorderedlist
     * @method queryCommandValue
     * @param { String } command 命令字符串
     * @return { String } 返回当前无序列表的类型，值为null或circle,disc,square,dash,dot
     * @example
     * ```javascript
     * editor.queryCommandValue( 'insertunorderedlist' );
     * ```
     */

    me.commands["insertorderedlist"] = me.commands["insertunorderedlist"] = {
        execCommand: function (command, style) {
            if (!style) {
                style = command.toLowerCase() == "insertorderedlist"
                    ? "decimal"
                    : "disc";
            }
            var me = this,
                range = this.selection.getRange(),
                filterFn = function (node) {
                    return node.nodeType == 1
                        ? node.tagName.toLowerCase() != "br"
                        : !domUtils.isWhitespace(node);
                },
                tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul",
                frag = me.document.createDocumentFragment();
            //去掉是因为会出现选到末尾，导致adjustmentBoundary缩到ol/ul的位置
            //range.shrinkBoundary();//.adjustmentBoundary();
            range.adjustmentBoundary().shrinkBoundary();
            var bko = range.createBookmark(true),
                start = getLi(me.document.getElementById(bko.start)),
                modifyStart = 0,
                end = getLi(me.document.getElementById(bko.end)),
                modifyEnd = 0,
                startParent,
                endParent,
                list,
                tmp;

            if (start || end) {
                start && (startParent = start.parentNode);
                if (!bko.end) {
                    end = start;
                }
                end && (endParent = end.parentNode);

                if (startParent === endParent) {
                    while (start !== end) {
                        tmp = start;
                        start = start.nextSibling;
                        if (!domUtils.isBlockElm(tmp.firstChild)) {
                            var p = me.document.createElement("p");
                            while (tmp.firstChild) {
                                p.appendChild(tmp.firstChild);
                            }
                            tmp.appendChild(p);
                        }
                        frag.appendChild(tmp);
                    }
                    tmp = me.document.createElement("span");
                    startParent.insertBefore(tmp, end);
                    if (!domUtils.isBlockElm(end.firstChild)) {
                        p = me.document.createElement("p");
                        while (end.firstChild) {
                            p.appendChild(end.firstChild);
                        }
                        end.appendChild(p);
                    }
                    frag.appendChild(end);
                    domUtils.breakParent(tmp, startParent);
                    if (domUtils.isEmptyNode(tmp.previousSibling)) {
                        domUtils.remove(tmp.previousSibling);
                    }
                    if (domUtils.isEmptyNode(tmp.nextSibling)) {
                        domUtils.remove(tmp.nextSibling);
                    }
                    var nodeStyle =
                        getStyle(startParent) ||
                        domUtils.getComputedStyle(startParent, "list-style-type") ||
                        (command.toLowerCase() == "insertorderedlist" ? "decimal" : "disc");
                    if (startParent.tagName.toLowerCase() == tag && nodeStyle == style) {
                        for (
                            var i = 0, ci, tmpFrag = me.document.createDocumentFragment();
                            (ci = frag.firstChild);
                        ) {
                            if (domUtils.isTagNode(ci, "ol ul")) {
                                //                                  删除时，子列表不处理
                                //                                  utils.each(domUtils.getElementsByTagName(ci,'li'),function(li){
                                //                                        while(li.firstChild){
                                //                                            tmpFrag.appendChild(li.firstChild);
                                //                                        }
                                //
                                //                                    });
                                tmpFrag.appendChild(ci);
                            } else {
                                while (ci.firstChild) {
                                    tmpFrag.appendChild(ci.firstChild);
                                    domUtils.remove(ci);
                                }
                            }
                        }
                        tmp.parentNode.insertBefore(tmpFrag, tmp);
                    } else {
                        list = me.document.createElement(tag);
                        setListStyle(list, style);
                        list.appendChild(frag);
                        tmp.parentNode.insertBefore(list, tmp);
                    }

                    domUtils.remove(tmp);
                    list && adjustList(list, tag, style);
                    range.moveToBookmark(bko).select();
                    return;
                }
                //开始
                if (start) {
                    while (start) {
                        tmp = start.nextSibling;
                        if (domUtils.isTagNode(start, "ol ul")) {
                            frag.appendChild(start);
                        } else {
                            var tmpfrag = me.document.createDocumentFragment(),
                                hasBlock = 0;
                            while (start.firstChild) {
                                if (domUtils.isBlockElm(start.firstChild)) {
                                    hasBlock = 1;
                                }
                                tmpfrag.appendChild(start.firstChild);
                            }
                            if (!hasBlock) {
                                var tmpP = me.document.createElement("p");
                                tmpP.appendChild(tmpfrag);
                                frag.appendChild(tmpP);
                            } else {
                                frag.appendChild(tmpfrag);
                            }
                            domUtils.remove(start);
                        }

                        start = tmp;
                    }
                    startParent.parentNode.insertBefore(frag, startParent.nextSibling);
                    if (domUtils.isEmptyNode(startParent)) {
                        range.setStartBefore(startParent);
                        domUtils.remove(startParent);
                    } else {
                        range.setStartAfter(startParent);
                    }
                    modifyStart = 1;
                }

                if (end && domUtils.inDoc(endParent, me.document)) {
                    //结束
                    start = endParent.firstChild;
                    while (start && start !== end) {
                        tmp = start.nextSibling;
                        if (domUtils.isTagNode(start, "ol ul")) {
                            frag.appendChild(start);
                        } else {
                            tmpfrag = me.document.createDocumentFragment();
                            hasBlock = 0;
                            while (start.firstChild) {
                                if (domUtils.isBlockElm(start.firstChild)) {
                                    hasBlock = 1;
                                }
                                tmpfrag.appendChild(start.firstChild);
                            }
                            if (!hasBlock) {
                                tmpP = me.document.createElement("p");
                                tmpP.appendChild(tmpfrag);
                                frag.appendChild(tmpP);
                            } else {
                                frag.appendChild(tmpfrag);
                            }
                            domUtils.remove(start);
                        }
                        start = tmp;
                    }
                    var tmpDiv = domUtils.createElement(me.document, "div", {
                        tmpDiv: 1
                    });
                    domUtils.moveChild(end, tmpDiv);

                    frag.appendChild(tmpDiv);
                    domUtils.remove(end);
                    endParent.parentNode.insertBefore(frag, endParent);
                    range.setEndBefore(endParent);
                    if (domUtils.isEmptyNode(endParent)) {
                        domUtils.remove(endParent);
                    }

                    modifyEnd = 1;
                }
            }

            if (!modifyStart) {
                range.setStartBefore(me.document.getElementById(bko.start));
            }
            if (bko.end && !modifyEnd) {
                range.setEndAfter(me.document.getElementById(bko.end));
            }
            range.enlarge(true, function (node) {
                return notExchange[node.tagName];
            });

            frag = me.document.createDocumentFragment();

            var bk = range.createBookmark(),
                current = domUtils.getNextDomNode(bk.start, false, filterFn),
                tmpRange = range.cloneRange(),
                tmpNode,
                block = domUtils.isBlockElm;

            while (
                current &&
                current !== bk.end &&
                domUtils.getPosition(current, bk.end) & domUtils.POSITION_PRECEDING
                ) {
                if (current.nodeType == 3 || dtd.li[current.tagName]) {
                    if (current.nodeType == 1 && dtd.$list[current.tagName]) {
                        while (current.firstChild) {
                            frag.appendChild(current.firstChild);
                        }
                        tmpNode = domUtils.getNextDomNode(current, false, filterFn);
                        domUtils.remove(current);
                        current = tmpNode;
                        continue;
                    }
                    tmpNode = current;
                    tmpRange.setStartBefore(current);

                    while (
                        current &&
                        current !== bk.end &&
                        (!block(current) || domUtils.isBookmarkNode(current))
                        ) {
                        tmpNode = current;
                        current = domUtils.getNextDomNode(current, false, null, function (
                            node
                        ) {
                            return !notExchange[node.tagName];
                        });
                    }

                    if (current && block(current)) {
                        tmp = domUtils.getNextDomNode(tmpNode, false, filterFn);
                        if (tmp && domUtils.isBookmarkNode(tmp)) {
                            current = domUtils.getNextDomNode(tmp, false, filterFn);
                            tmpNode = tmp;
                        }
                    }
                    tmpRange.setEndAfter(tmpNode);

                    current = domUtils.getNextDomNode(tmpNode, false, filterFn);

                    var li = range.document.createElement("li");

                    li.appendChild(tmpRange.extractContents());
                    if (domUtils.isEmptyNode(li)) {
                        var tmpNode = range.document.createElement("p");
                        while (li.firstChild) {
                            tmpNode.appendChild(li.firstChild);
                        }
                        li.appendChild(tmpNode);
                    }
                    frag.appendChild(li);
                } else {
                    current = domUtils.getNextDomNode(current, true, filterFn);
                }
            }
            range.moveToBookmark(bk).collapse(true);
            list = me.document.createElement(tag);
            setListStyle(list, style);
            list.appendChild(frag);
            range.insertNode(list);
            //当前list上下看能否合并
            adjustList(list, tag, style);
            //去掉冗余的tmpDiv
            for (
                var i = 0, ci, tmpDivs = domUtils.getElementsByTagName(list, "div");
                (ci = tmpDivs[i++]);
            ) {
                if (ci.getAttribute("tmpDiv")) {
                    domUtils.remove(ci, true);
                }
            }
            range.moveToBookmark(bko).select();
        },
        queryCommandState: function (command) {
            var tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul";
            var path = this.selection.getStartElementPath();
            for (var i = 0, ci; (ci = path[i++]);) {
                if (ci.nodeName == "TABLE") {
                    return 0;
                }
                if (tag == ci.nodeName.toLowerCase()) {
                    return 1;
                }
            }
            return 0;
        },
        queryCommandValue: function (command) {
            var tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul";
            var path = this.selection.getStartElementPath(),
                node;
            for (var i = 0, ci; (ci = path[i++]);) {
                if (ci.nodeName == "TABLE") {
                    node = null;
                    break;
                }
                if (tag == ci.nodeName.toLowerCase()) {
                    node = ci;
                    break;
                }
            }
            return node
                ? getStyle(node) || domUtils.getComputedStyle(node, "list-style-type")
                : null;
        }
    };
};
